from rest_framework import serializers

from apps.QuestionManagement.models import Questions


class QuestionsSerializer(serializers.ModelSerializer):
    created_user = serializers.SerializerMethodField()
    updated_user = serializers.SerializerMethodField()

    class Meta:
        model = Questions
        fields = "__all__"

    def get_created_user(self, obj):
        """
        获取创建人的用户名
        """
        return obj.created_user.username if obj.created_user else None

    def get_updated_user(self, obj):
        """
        获取更新人的用户名
        """
        return obj.updated_user.username if obj.updated_user else None


class QuestionsListSerializer(serializers.ModelSerializer):
    created_user = serializers.SerializerMethodField()
    updated_user = serializers.SerializerMethodField()

    class Meta:
        model = Questions
        fields = "__all__"

    def get_created_user(self, obj):
        """
        获取创建人的用户名
        """
        return obj.created_user.username if obj.created_user else None

    def get_updated_user(self, obj):
        """
        获取更新人的用户名
        """
        return obj.updated_user.username if obj.updated_user else None


class QuestionsCreateUpdateSerializer(serializers.ModelSerializer):
    """
    序列化器：用于创建和更新试题时的校验
    """

    class Meta:
        model = Questions
        fields = '__all__'

    def to_internal_value(self, data):
        """
        覆盖此方法，以便从前端接收数组并将其转换为分号分隔的字符串。
        """
        # 将数组字段转换为分号分隔的字符串
        for field in ['options', 'answer', 'keywords', 'classify']:
            if field in data and isinstance(data[field], list):
                # 将列表中的元素转换为字符串后再使用 join
                data[field] = ';'.join(map(str, data[field]))

        # 填充用户 ID
        user_id = data.get('user_id')
        if user_id:
            data['created_user'] = user_id
            data['updated_user'] = user_id

        return super().to_internal_value(data)

    def to_representation(self, instance):
        """
        覆盖此方法，将分号分隔的字符串转换为数组。
        """
        data = super().to_representation(instance)

        # 将字符串转换为数组（用分号分隔）
        for field in ['options', 'answer', 'keywords', 'classify']:
            if field in data and data[field]:
                data[field] = data[field].split(';')

        return data

    def validate_options(self, value):
        """校验选项字段，确保选项是以分号分隔并且至少有两个选项"""
        qst_type = self.initial_data.get('type')
        if qst_type != 'short':
            options_list = value.split(';')
            if len(options_list) < 2:
                raise serializers.ValidationError("选项数量必须大于两个。")
        return value

    def validate_answer(self, value):
        """校验答案字段，确保答案是选项中的有效下标（对于判断题）。"""
        qst_type = self.initial_data.get('type')
        options_list = self.initial_data.get('options', '').split(';')

        if qst_type == 'judge':
            # 判断题的答案必须是选项的有效下标（0 或 1）
            answer_list = value.split(';')
            for answer in answer_list:
                if int(answer) not in [0, 1]:
                    raise serializers.ValidationError("判断题答案的下标必须是 0 或 1，表示选择 'true' 或 'false'。")
        elif qst_type != 'short':
            # 单选题或多选题，答案必须是选项索引
            answer_list = value.split(';')
            for answer in answer_list:
                if int(answer) >= len(options_list) or int(answer) < 0:
                    raise serializers.ValidationError("答案中的选项索引必须在选项列表的有效范围内。")
            return ';'.join(answer_list)

        return value

    def validate_keywords(self, value):
        """
        校验简答题的关键词，确保是分号分隔的关键词列表。对于简答题，关键词不能为空。
        """
        qst_type = self.initial_data.get('type')

        if qst_type != 'short':
            return value  # 非简答题，允许为空

        # 简答题的关键词不能为空
        if not value:
            raise serializers.ValidationError("简答题时关键词不能为空。")

        return value

    def validate_classify(self, value):
        """
        校验考试类别，确保是分号分隔的字符串
        """
        return value

    def validate(self, data):
        """
        根据题型进行整体校验
        """
        options_list = data.get('options', '').split(';')
        answer_list = data.get('answer', '').split(';')
        kwd_list = data.get('keywords', '').split(';')
        qst_type = data.get('type')

        # 根据题型进行校验
        if qst_type == 'single':
            if len(answer_list) != 1:
                raise serializers.ValidationError("单选题必须有且只有一个正确答案。")
            if len(options_list) < 4:
                raise serializers.ValidationError("单选题至少有四个选项")
        elif qst_type == 'multiple':
            if len(answer_list) < 2:
                raise serializers.ValidationError("多选题必须有至少两个正确答案。")
            if len(options_list) < 4:
                raise serializers.ValidationError("多选题至少有四个选项")
        elif qst_type == 'judge':
            if len(options_list) != 2:
                raise serializers.ValidationError("判断题必须有且只有两个选项。")
            if len(answer_list) < 1:
                raise serializers.ValidationError("判断题必须有且只有一个答案。")
        elif qst_type == 'short':
            if len(kwd_list) < 1:
                raise serializers.ValidationError("简答题必须提供一个关键词")

        return data
